// AcctDlg.cpp : implementation file
//

#include "stdafx.h"
#include "LightspeedTraderAPIDemo.h"
#include "AcctDlg.h"
#include "PositionDlg.h"
#include "OrderDlg.h"

//enum used for API Function Indexing
enum ACCT_INDEX_STATIC {
	TRADER_ID,
	FIRM,

	END_OF_STATIC_VALUES //Indicates end of static index values
};

enum ACCT_INDEX_DYNAMIC {
	OPEN_PL = END_OF_STATIC_VALUES,
	MARKED_PL,
	NET_PL,

	END_OF_DYNAMIC_VALUES //indicates end of dynamic index values
};

//order change messages happen less frequently than account change messages
enum ACCT_INDEX_ORDERCHANGE_VALUES {
	MARGIN_FACTOR = END_OF_DYNAMIC_VALUES,
	CLOSED_PL,
	MIN_CLOSED_PL,
	MAX_CLOSED_PL,
	MAX_INTRADAY_VALUE,
	BP_IN_USE,
	BASE_BP,
	FLOATING_BP,
	EQUITY,
	RUNNING_BALANCE,
	VALUE,
	LONG_VALUE,
	SHORT_VALUE,
	DOLLAR_VALUE,
	LONG_DOLLAR_VALUE,
	SHORT_DOLLAR_VALUE,
	NET_DOLLAR_VALUE,
	OPEN_POSITION_COUNT,
	LONG_OPEN_POSITION_COUNT,
	SHORT_OPEN_POSITION_COUNT,
	PENDING_ORDERS_COUNT,
	PENDING_BUY_ORDERS_COUNT,
	PENDING_SELL_ORDERS_COUNT,
	SHARES_TRADED,
	NUM_TRADES,
	NUM_EXECUTIONS,
	ADDED_LIQUIDITY,
	ADDED_LIQUIDITY_EXECUTIONS,
	REMOVED_LIQUIDITY,
	REMOVED_LIQUIDITY_EXECUTIONS,

	END_OF_ORDERCHANGE_VALUES
};

// AcctDlg dialog

IMPLEMENT_DYNAMIC(AcctDlg, CModelessDialog)

AcctDlg::AcctDlg(CWnd* pParent /*=NULL*/)
	: CModelessDialog(AcctDlg::IDD, pParent)
	, m_AcctDataListCtrl(CListCtrl())
	, account(0)
{
	SetAPIFunctions();
}

AcctDlg::~AcctDlg()
{
	//detach from account
	if (account)
	{
		account->L_Detach(this);
	}
}

BOOL AcctDlg::Create(CWnd *pParentWnd /*= CWnd::FromHandle(L_GetMainWnd())*/)
{
	return __super::Create(AcctDlg::IDD, pParentWnd);
}

void AcctDlg::DoDataExchange(CDataExchange* pDX)
{
	CModelessDialog::DoDataExchange(pDX);

	DDX_Control(pDX,IDC_ACCTLIST,m_AcctDataListCtrl);
}

BOOL AcctDlg::OnInitDialog()
{
	__super::OnInitDialog();

	DWORD style = m_AcctDataListCtrl.GetExtendedStyle();
	style |= LVS_EX_FULLROWSELECT;
	style |= LVS_EX_GRIDLINES;
	style |= LVS_EX_DOUBLEBUFFER;
	m_AcctDataListCtrl.SetExtendedStyle(style);

	m_AcctDataListCtrl.InsertColumn(0,"API Function", LVCFMT_LEFT, 110, 0);
	m_AcctDataListCtrl.InsertColumn(1,"Value", LVCFMT_LEFT, 110, 1);

	//get account
	account = L_GetAccount();
	InitializeDataCtrlRows();

	//attach to account to recieve changes
	account->L_Attach(this);

	return TRUE;
}

void AcctDlg::SetAPIFunctions()
{
	//clear APIFunction array
	memset(APIFunctions,NULL,sizeof(APIFunctions));

	strcpy_s(APIFunctions[TRADER_ID],"Trader ID");
	strcpy_s(APIFunctions[FIRM],"Firm");
	strcpy_s(APIFunctions[MARGIN_FACTOR],"Margin Factor");
	strcpy_s(APIFunctions[CLOSED_PL],"Closed PL");
	strcpy_s(APIFunctions[OPEN_PL],"Open PL");
	strcpy_s(APIFunctions[NET_PL],"Net PL");
	strcpy_s(APIFunctions[MARKED_PL],"Marked PL");
	strcpy_s(APIFunctions[MIN_CLOSED_PL],"Min Closed PL");
	strcpy_s(APIFunctions[MAX_CLOSED_PL],"Max Closed PL");
	strcpy_s(APIFunctions[MAX_INTRADAY_VALUE],"Max Intraday Value");
	strcpy_s(APIFunctions[BP_IN_USE],"BP In Use");
	strcpy_s(APIFunctions[BASE_BP],"Base BP");
	strcpy_s(APIFunctions[FLOATING_BP],"Floating BP Multiple");
	strcpy_s(APIFunctions[EQUITY],"Equity");
	strcpy_s(APIFunctions[RUNNING_BALANCE],"Running Balance");
	strcpy_s(APIFunctions[VALUE],"Value");
	strcpy_s(APIFunctions[LONG_VALUE],"Long Value");
	strcpy_s(APIFunctions[SHORT_VALUE],"Short Value");
	strcpy_s(APIFunctions[DOLLAR_VALUE],"Dollar Value");
	strcpy_s(APIFunctions[LONG_DOLLAR_VALUE],"Long Dollar Value");
	strcpy_s(APIFunctions[SHORT_DOLLAR_VALUE],"Short Dollar Value");
	strcpy_s(APIFunctions[NET_DOLLAR_VALUE],"Net Dollar Value");
	strcpy_s(APIFunctions[OPEN_POSITION_COUNT],"Open Positions");
	strcpy_s(APIFunctions[LONG_OPEN_POSITION_COUNT],"Open Long Positions");
	strcpy_s(APIFunctions[SHORT_OPEN_POSITION_COUNT],"Open Short Positions");
	strcpy_s(APIFunctions[PENDING_ORDERS_COUNT],"Pending Orders");
	strcpy_s(APIFunctions[PENDING_BUY_ORDERS_COUNT],"Pending Buy Orders");
	strcpy_s(APIFunctions[PENDING_SELL_ORDERS_COUNT],"Pending Sell Orders");
	strcpy_s(APIFunctions[SHARES_TRADED],"Shares Traded");
	strcpy_s(APIFunctions[NUM_TRADES],"Number of Trades");
	strcpy_s(APIFunctions[NUM_EXECUTIONS],"Number of Executions");
	strcpy_s(APIFunctions[ADDED_LIQUIDITY],"Added Liquidity");
	strcpy_s(APIFunctions[ADDED_LIQUIDITY_EXECUTIONS],"Added Liquidity Executions");
	strcpy_s(APIFunctions[REMOVED_LIQUIDITY],"Removed Liquidity");
	strcpy_s(APIFunctions[REMOVED_LIQUIDITY_EXECUTIONS],"Removed Liquidity Executions");
}

void AcctDlg::InitializeDataCtrlRows()
{
	for (int i = 0; i < END_OF_ORDERCHANGE_VALUES; ++i)
	{
		m_AcctDataListCtrl.InsertItem(i,APIFunctions[i]);
	}
	InsertStaticValues();
	UpdateDynamicAccountValues();
	UpdateOrderChangeValues();
}

void AcctDlg::InsertStaticValues()
{
	m_AcctDataListCtrl.SetRedraw(FALSE); //disable redraw to reduce control flickering
	for (int i = 0; i < END_OF_STATIC_VALUES; ++i)
	{
		m_AcctDataListCtrl.SetItemText(i, 1, GetTextForFunction(i));
	}
	m_AcctDataListCtrl.SetRedraw(TRUE);
}

void AcctDlg::UpdateDynamicAccountValues()
{
	m_AcctDataListCtrl.SetRedraw(FALSE); //disable redraw to reduce control flickering
	for (int i = END_OF_STATIC_VALUES; i < END_OF_DYNAMIC_VALUES; ++i)
	{
		m_AcctDataListCtrl.SetItemText(i, 1, GetTextForFunction(i));
	}
	m_AcctDataListCtrl.SetRedraw(TRUE);
}

void AcctDlg::UpdateOrderChangeValues()
{
	m_AcctDataListCtrl.SetRedraw(FALSE); //disable redraw to reduce control flickering
	for (int i = END_OF_DYNAMIC_VALUES; i < END_OF_ORDERCHANGE_VALUES; ++i)
	{
		m_AcctDataListCtrl.SetItemText(i, 1, GetTextForFunction(i));
	}
	m_AcctDataListCtrl.SetRedraw(TRUE);
}

//will map index enums to the equivilant API functions
CString AcctDlg::GetTextForFunction(int function)
{
	CString retString = "";
	switch(function)
	{
	case TRADER_ID:
		{
			retString = account->L_TraderId();
		}
		break;
	case FIRM:
		{
			retString = account->L_Firm();
		}
		break;
	case MARGIN_FACTOR:
		{
			retString.Format("%.2f",account->L_MarginFactor());
		}
		break;
	case CLOSED_PL:
		{
			retString.Format("%.2f",account->L_ClosedPL());
		}
		break;
	case OPEN_PL:
		{
			retString.Format("%.2f",account->L_OpenPL());
		}
		break;
	case NET_PL:
		{
			retString.Format("%.2f",account->L_NetPL());
		}
		break;
	case MARKED_PL:
		{
			retString.Format("%.2f",account->L_MarkedPL());
		}
		break;
	case MIN_CLOSED_PL:
		{
			retString.Format("%.2f",account->L_MinClosedPL());
		}
		break;
	case MAX_CLOSED_PL:
		{
			retString.Format("%.2f",account->L_MaxClosedPL());
		}
		break;
	case MAX_INTRADAY_VALUE:
		{
			retString.Format("%.2f",account->L_MaxIntradayDollarValue());
		}
		break;
	case BP_IN_USE:
		{
			retString.Format("%.2f",account->L_BuyingPowerInUse());
		}
		break;
	case BASE_BP:
		{
			retString.Format("%.2f",account->L_BaseBuyingPower());
		}
		break;
	case FLOATING_BP:
		{
			retString.Format("%.2f",account->L_FloatingBPMultiple());
		}
		break;
	case EQUITY:
		{
			retString.Format("%.2f",account->L_Equity());
		}
		break;
	case RUNNING_BALANCE:
		{
			retString.Format("%.2f",account->L_RunningBalance());
		}
		break;
	case VALUE:
		{
			retString.Format("%.2f",account->L_RunningBalance());
		}
		break;
	case LONG_VALUE:
		{
			retString.Format("%.2f",account->L_LongValue());
		}
		break;
	case SHORT_VALUE:
		{
			retString.Format("%.2f",account->L_ShortValue());
		}
		break;
	case DOLLAR_VALUE:
		{
			retString.Format("%.2f",account->L_DollarValue());
		}
		break;
	case LONG_DOLLAR_VALUE:
		{
			retString.Format("%.2f",account->L_LongDollarValue());
		}
		break;
	case SHORT_DOLLAR_VALUE:
		{
			retString.Format("%.2f",account->L_ShortDollarValue());
		}
		break;
	case NET_DOLLAR_VALUE:
		{
			retString.Format("%.2f",account->L_NetDollarValue());
		}
		break;
	case OPEN_POSITION_COUNT:
		{
			retString.Format("%d",account->L_OpenPositionsCount());
		}
		break;
	case LONG_OPEN_POSITION_COUNT:
		{
			retString.Format("%d",account->L_LongOpenPositionsCount());
		}
		break;
	case SHORT_OPEN_POSITION_COUNT:
		{
			retString.Format("%d",account->L_ShortOpenPositionsCount());
		}
		break;
	case PENDING_ORDERS_COUNT:
		{
			retString.Format("%d",account->L_PendingOrdersCount());
		}
		break;
	case PENDING_BUY_ORDERS_COUNT:
		{
			retString.Format("%d",account->L_PendingBuyOrdersCount());
		}
		break;
	case PENDING_SELL_ORDERS_COUNT:
		{
			retString.Format("%d",account->L_PendingSellOrdersCount());
		}
		break;
	case SHARES_TRADED:
		{
			retString.Format("%d",account->L_SharesTraded());
		}
		break;
	case NUM_TRADES:
		{
			retString.Format("%d",account->L_NumTrades());
		}
		break;
	case NUM_EXECUTIONS:
		{
			retString.Format("%d",account->L_NumExecutions());
		}
		break;
	case ADDED_LIQUIDITY:
		{
			retString.Format("%d",account->L_AddedLiquidity());
		}
		break;
	case ADDED_LIQUIDITY_EXECUTIONS:
		{
			retString.Format("%d",account->L_AddedLiquidityExecutions());
		}
		break;
	case REMOVED_LIQUIDITY:
		{
			retString.Format("%d",account->L_RemovedLiquidity());
		}
		break;
	case REMOVED_LIQUIDITY_EXECUTIONS:
		{
			retString.Format("%d",account->L_RemovedLiquidityExecutions());
		}
		break;
	}

	return retString;
}

//L_Oberver
void AcctDlg::HandleMessage(L_Message const *pMsg)
{
	switch(pMsg->L_Type())
	{
	case L_MsgAccountChange::id:
		{
			UpdateDynamicAccountValues();
		}
		break;
	case L_MsgOrderChange::id:
		{
			UpdateOrderChangeValues();
		}
		break;
	}
}


BEGIN_MESSAGE_MAP(AcctDlg, CModelessDialog)
	ON_WM_SIZE()
	ON_COMMAND(ID_VIEW_POSITIONS, OnViewPositions)
	ON_COMMAND(ID_VIEW_ORDERS, OnViewOrders)
END_MESSAGE_MAP()

// AcctDlg message handlers

void AcctDlg::OnSize(UINT nType, int cx, int cy)
{
	__super::OnSize(nType, cx, cy);

	ResizeControls();
}

void AcctDlg::ResizeControls()
{
	if (m_hWnd && m_AcctDataListCtrl.m_hWnd)
	{
		RECT Rect;
		GetClientRect(&Rect);

		RECT ctrlRect;
		m_AcctDataListCtrl.GetWindowRect(&ctrlRect);
		ScreenToClient(&ctrlRect);

		Rect.top = ctrlRect.top;

		m_AcctDataListCtrl.MoveWindow(&Rect);
	}
}

void AcctDlg::OnViewPositions()
{
	PositionDlg *pDlg = new PositionDlg;
	if (! CLightspeedTraderAPIDemoApp::GetInstance()->CreateDlg(pDlg))
	{
		delete pDlg;
	}

}

void AcctDlg::OnViewOrders()
{
	OrderDlg *pDlg = new OrderDlg;
	if (! CLightspeedTraderAPIDemoApp::GetInstance()->CreateDlg(pDlg))
	{
		delete pDlg;
	}
}